#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include "filelock.h"

#define FILE_PATH  "./text.txt"

static void print_err(char *str, int line, int err_no) {
    printf("line %d, %s: %s\n", line, str, strerror(err_no));
    exit(-1);
}

void *th_fun(void *arg) {
    /* 如果不加O_APPEND追加标志，可能出现内容覆盖情况：
     * 因为线程A open以后，写位置在固定位置，线程B open甚至写了某些内容后，线程A的写位置正常是要移动到末尾，
     * 而没有O_APPEND标志时，线程A并不会移动写位置，这样容易出现相互覆盖的情况
     * */
    int fd = open(FILE_PATH, O_WRONLY | O_CREAT | O_APPEND, 0664);
    if (fd < 0) print_err("open file fail", __LINE__, errno);

    int whichth = *(int *)arg;
    char *str1;
    char *str2;

    if (whichth == 0) {
        str1 = "A:hello ";
        str2 = "world";
    }
    else {
        str1 = "B:1111 ";
        str2 = "22222222";
    }

    int len1 = strlen(str1);
    int len2 = strlen(str2);

    while (1) {
//        flock(fd, LOCK_EX);
        filelock_lockwrite(fd, 1);

        write(fd, str1, len1);
        write(fd, str2, len2);
        write(fd, "\n", 1);

        filelock_unlockwrite(fd);
//        flock(fd, LOCK_UN);
    }
}

/**
 * 示例：2个线程同时写同一个文件，对文件进行写加锁，确保文件内容完整性
 */
void testfilelock() {
    pthread_t th1, th2;
    void *tret;
    int thno1 = 0, thno2 = 1;
    pthread_create(&th1, NULL, th_fun, &thno1);
    pthread_create(&th2, NULL, th_fun, &thno2);

    pthread_join(th1, &tret);
    pthread_join(th2, &tret);
}

int main() {
    testfilelock();
    return 0;
}
